import Vue from "vue";
const resolution = 1; //isFinite(window.devicePixelRatio) ? window.devicePixelRatio : 1;
const is_support_webp =
  document
    .createElement("canvas")
    .toDataURL("image/webp")
    .indexOf("data:image/webp") == 0;
export function init_loader_number_res(
  texture_url = "home/shuzi_02.png",
  texture_name = "big_numbers"
) {
  return function(loader) {
    loader.add(texture_name, texture_url);
  };
}

function initLoaderNumber(loader) {
  loader.initNumbers = (texture_url, texture_name) => {
    init_loader_number_res((texture_name, texture_url))(loader);
  };
  const getMulNumberSprite = (
    str,
    numbers_texture,
    number_frames,
    style = {}
  ) => {
    const numbers_container = new PIXI.Container();
    const { word_spacing = 0.15 } = style;
    const { width, height } = numbers_texture;
    const unit_width = width / 12;
    str.split("").forEach((char, i) => {
      const $num = getOneNumberSprite(char, numbers_texture, number_frames);
      $num.x = (1 + word_spacing) * unit_width * i;
      numbers_container.addChild($num);
    });
    return numbers_container;
  };
  const getOneNumberSprite = (init_char, numbers_texture, number_frames) => {
    const num_sprite = new PIXI.Sprite(numbers_texture.clone());
    num_sprite.setNumber = char => {
      char || (char = "0");
      num_sprite.texture.frame = number_frames.get(char);
    };
    num_sprite.setNumber(init_char);
    return num_sprite;
  };
  loader.getNumberSprite = (init_char, texture_name = "big_numbers", style) => {
    const { resources } = loader;
    const numbers_texture = resources[texture_name].texture;
    const { width, height } = numbers_texture;
    const unit_width = width / 12;

    const number_frames = (numbers_texture.number_frames = new Map());
    number_frames.set(".", new PIXI.Rectangle(0, 0, unit_width, 49));
    number_frames.set("/", new PIXI.Rectangle(unit_width, 0, unit_width, 49));
    for (let i = 0; i <= 9; i += 1) {
      number_frames.set(i + "", new PIXI.Rectangle(76 + i * 38, 0, 38, 49));
    }

    loader.getNumberSprite = (
      init_char,
      texture_name = "big_numbers",
      style
    ) => {
      init_char = "" + init_char;
      const { resources } = loader;
      const numbers_texture = resources[texture_name].texture;
      if (init_char.length === 1) {
        return getOneNumberSprite(
          init_char,
          numbers_texture,
          numbers_texture.number_frames,
          style
        );
      } else {
        return getMulNumberSprite(
          init_char,
          numbers_texture,
          numbers_texture.number_frames
        );
      }
    };
    return loader.getNumberSprite(init_char, texture_name, style);
  };
}

const preLoaderCache = {};
const isPreLoadered = {};
export function preLoader(id) {
  if (isPreLoadered[id]) {
    console.log("模块", id, "已经加载过");
    return;
  }
  const loader_resources = preLoaderCache[id];
  if (loader_resources) {
    console.log("开始预加载", id, "模块");
    const loader = loaderWrapper(id);
    if (loader_resources) {
      for (let key in loader_resources) {
        const res_url = loader_resources[key];
        if (res_url instanceof Function) {
          res_url(loader);
        } else {
          loader.add(key, res_url);
        }
      }
      loader.startLoad();
      loader.once("fully-loaded", () => {
        console.log("预加载", id, "模块完成");
      });
    }
  }
}
const loaderWrapper = (id, is_auto_reload = true) => {
  const loader = (isPreLoadered[id] = new PIXI.loaders.Loader(resource_href));
  loader._parent_level = 0;

  if (is_support_webp) {
    loader.pre((resource, next) => {
      resource.url += "?imageMogr2/format/webp";
      next();
    });
  }
  const reloaders = [];
  loader.onError.add((err, loader, resource) => {
    reloaders.push(resource);
  });
  loader.startLoad = () => {
    if (!is_auto_reload) {
      Raven.captureMessage(
        `resource load error:(${reloaders.length})\n` +
          reloaders
            .map(resource => `[${resource.name}] ${resource.url}`)
            .join("\n"),
        {
          logger: "Network"
        }
      );
      // 尝试性触发绘图功能
      loader.load(() => {
        loader.emit("fully-loaded");
      });
    } else {
      loader.load(() => {
        if (reloaders.length) {
          console.error(
            `resource load error:(${reloaders.length})\n` +
              reloaders
                .map(resource => `\t[${resource.name}] ${resource.url}`)
                .join("\n")
          );
          const target_parent_level = loader._parent_level + 1;
          // 有加载错误的资源，开始重载
          var reloader = loaderWrapper(
            id + "-" + target_parent_level,
            loader._parent_level < 10 //最多重载10次，再多就异常报错
          );
          reloader._parent_level = target_parent_level;
          reloaders.forEach(resource => {
            reloader.add(resource.name, resource.url);
          });
          reloader.startLoad();
          reloader.once("fully-loaded", () => {
            Object.assign(loader.resources, reloader.resources);
            loader.emit("fully-loaded");
          });
        } else {
          loader.emit("fully-loaded");
        }
      });
    }
  };
  return loader;
};

const stageComponentSuper = {
  data(new_data) {
    return function() {
      const data = Object.assign(
        {
          // 聊天框
          msg_box: {
            custom_input_value: "",
            is_open: false
          }
        },
        new_data()
      );
      return data;
    };
  },
  created(old_handle, options) {
    return function() {
      const offs = (this.offs = []);
      const unwatchers = (this.unwatchers = []);
      this.clearWatch = () => {
        unwatchers.forEach(unwatcher => unwatcher());
        unwatchers.length = 0;
      };
      const app = (this.app = new PIXI.Application()); //{ forceCanvas: true }
      const loader = (this.loader = loaderWrapper(options.name));

      this.$parent.progress = 0;
      loader.onProgress.add((loader, cur_load_resouce) => {
        this.$parent.progress = loader.progress;
      });
      const loader_resources = options.resources;
      if (loader_resources) {
        for (let key in loader_resources) {
          const res_url = loader_resources[key];
          if (res_url instanceof Function) {
            res_url(loader);
          } else {
            loader.add(key, res_url);
          }
        }
      }
      /* 中间件 */
      initLoaderNumber(loader);

      old_handle instanceof Function && old_handle.call(this);
    };
  },
  mounted(old_handle, options) {
    return function() {
      const app = this.app;
      const root_node = this.$refs.root_node;

      const draw_app = () => {
        clearTimeout(this.__draw_app_ti);
        try {
          this.draw_app();
        } catch (e) {
          console.error("DRAW ERROR:", e);
          this.__draw_app_ti = setTimeout(draw_app, 200);
          Raven.captureException(e);
        }
      };

      this._resize_handler = e => {
        setTimeout(() => {
          if (!app.view) {
            return;
          }
          if (
            app.renderer.width !== root_node.clientWidth * resolution ||
            app.renderer.height !== root_node.clientHeight * resolution
          ) {
            this._resize_handler(e);
          }
        }, 250);
        app.renderer.resize(
          root_node.clientWidth * resolution,
          root_node.clientHeight * resolution
        );
        draw_app();
      };
      old_handle instanceof Function && old_handle.call(this);
      window.addEventListener("resize", this._resize_handler);
      // alert(['target inited',root_node.clientWidth,root_node.clientHeight]);
      app.renderer.resize(
        root_node.clientWidth * resolution,
        root_node.clientHeight * resolution
      );
      this.loader.startLoad();
      this.loader.once("fully-loaded", () => {
        if (app.view) {
          window.__CURENT_STAGE__ = options.name;
          // maybe run on after destroyed
          root_node.appendChild(app.view);
          draw_app();
          if (options.next_stages instanceof Array) {
            options.next_stages.forEach(preLoader);
          }
        }
      });
    };
  },
  destroyed(old_handle) {
    return function() {
      this.app.destroy();
      this.loader.reset();
      this.loader = null;
      this.clearWatch();
      this.offs.forEach(remover => remover());
      window.removeEventListener("resize", this._resize_handler);
      old_handle instanceof Function && old_handle.call(this);
    };
  },
  props(old_val) {
    const props = Object.assign(
      {
        player: {
          type: Object,
          default() {
            return {
              id: "USERID",
              info: {
                username: "",
                headimgurl: "",
                cards: 0,
                points: 0,
                source_cards: 0,
                fake: true
              },
              status: 0,
              actions: [],
              card_list: []
            };
          }
        },
        room: {
          type: Object,
          default() {
            return {
              id: "",
              status: "",
              status: 0,
              owner: null,
              players: []
            };
          }
        }
      },
      old_val
    );
    return props;
  }
};
export function stageComponentGenerator(obj) {
  const res = Object.assign({}, obj);
  for (let key in stageComponentSuper) {
    res[key] = stageComponentSuper[key](res[key], obj);
  }
  return res;
}

export function on(events, eventname, handle) {
  events.on(eventname, handle);
  return function() {
    events.off(eventname, handle);
  };
}

export function vueStageComponentWrapper(id, extend_obj) {
  preLoaderCache[id] = extend_obj.resources;
  return Vue.component(
    id,
    stageComponentGenerator({
      name: id,
      template: `<div ref="root_node" class="stage-component ${id}"></div>`,
      ...extend_obj
    })
  );
}
